package com.augurit.wf.mgmt.dao;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;
import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
import org.springframework.stereotype.Repository;
import org.springside.modules.orm.Page;

import com.augurit.common.base.dao.BaseDao;
import com.augurit.common.util.PageUtils;
import com.augurit.common.util.lang.StringUtils;
import com.augurit.wf.common.entity.Jbpm4Execution;
import com.augurit.wf.common.entity.Jbpm4Task;
import com.augurit.wf.common.util.WfUtils;
import com.augurit.wf.mgmt.web.form.WfProcessInstanceForm;

@Repository
public class WfProcessInstanceDao extends BaseDao<Jbpm4Execution, Long>{
	public static final String EXECUTION_STATE_ACTIVE= "active";//执行实例状态为活动
	public static final String EXECUTION_STATE_SUSPENDED = "suspended";//执行实例状态为挂起
	
	/**
	 * 根据流程实例ID和活动实例状态获取当前活动实例集合
	 * @param processInstanceId 流程实例ID
	 * @param state 活动实例状态，其值应该是EXECUTION_STATE_ACTIVE和EXECUTION_STATE_SUSPENDED常量
	 * @return 当前活动实例集合
	 */
	@SuppressWarnings("unchecked")
	public List<Jbpm4Execution> getCurrentActivityInstancesByProcessInstanceId(Long processInstanceId,String state){
		StringBuilder hql = new StringBuilder("select exe from Jbpm4Execution exe,Jbpm4HistProcinst pn where pn.procInstDbId=exe.processInstanceId and exe.processInstanceId=:processInstanceId ");
		if(EXECUTION_STATE_ACTIVE.equals(state))
			hql.append("and exe.state like :state and exe.state != 'inactive-concurrent-root'");
		else if(EXECUTION_STATE_SUSPENDED.equals(state)){
			hql.append("and exe.state=:state");
		}
		
		
		Session session = this.getSession();
		Query query = session.createQuery(hql.toString());
		
		query.setLong("processInstanceId", processInstanceId);
		if(EXECUTION_STATE_ACTIVE.equals(state))
			query.setString("state", "%" + state + "%");
		else if(EXECUTION_STATE_SUSPENDED.equals(state)){
			query.setString("state", state);
		}
		
		List<Jbpm4Execution> jbpm4Executions = query.list();
		
		return jbpm4Executions;
	}
	
	/**
	 * 根据流程实例ID获取当前活动实例集合
	 * @param processInstanceId 流程实例ID
	 * @return 当前活动实例集合
	 */
	@SuppressWarnings("unchecked")
	public List<Jbpm4Execution> getCurrentActivityInstancesByProcessInstanceId(Long processInstanceId){
		StringBuilder hql = new StringBuilder("select exe from Jbpm4Execution exe,Jbpm4HistProcinst pn where pn.procInstDbId=exe.processInstanceId and exe.processInstanceId=:processInstanceId ");
		
		Session session = this.getSession();
		Query query = session.createQuery(hql.toString());
		query.setLong("processInstanceId", processInstanceId);
		
		List<Jbpm4Execution> jbpm4Executions = query.list();
		return jbpm4Executions;
	}
	
	/**
	 * 修改历史任务对象状态
	 * @param state 任务状态
	 * @param taskIds 要修改的任务ID集合
	 * @return 修改成功时返回true，失败返回false
	 */
	public boolean updateHistoryTaskState(String state,List<Long> taskIds){
		StringBuilder hql = new StringBuilder("update HistoryTaskImpl ht set ht.state=:state where ");
		
		for (int i=0;i<taskIds.size();i++) {
			hql.append("ht.dbid=:taskId"+i + " or ");
		}
		
		hql.delete(hql.lastIndexOf(" or "),hql.length());
		
		
		Session session = this.getSession();
		Query query = session.createQuery(hql.toString());
		query.setParameter("state", state);
		
		for (int i=0;i<taskIds.size();i++) {
			Long task = taskIds.get(i);
			query.setParameter("taskId"+i, task);
		}
		
		query.executeUpdate();
		return false;
	}
	
	/**
	 * 修改工作项
	 * @param jbpm4Task 要修改的工作项对象
	 * @return 修改成功时返回true
	 */
	public boolean updateTask(Jbpm4Task jbpm4Task)throws Exception{
		Session session = this.getSession();
		session.update(jbpm4Task);
		return true;
	}
	
	/**
	 * 修改历史工作项
	 * @param historyTaskImpl 要修改的历史工作项对象
	 * @return 修改成功时返回true
	 */
	public boolean updateHisTask(HistoryTaskImpl historyTaskImpl)throws Exception{
		Session session = this.getSession();
		session.update(historyTaskImpl);
		return true;
	}
	
	/**
	 * 查询流程实例
	 * @param page 分页对象
	 * @param form 流程实例对象FORM对象
	 * @return WfProcessInstanceForm集合
	 */
	@SuppressWarnings("unchecked")
	public List<WfProcessInstanceForm> search(Page<WfProcessInstanceForm> page, WfProcessInstanceForm form){
		if (form != null && page != null) {
			//查找流程实例集合语句
			StringBuffer hql = new StringBuffer("select new com.augurit.wf.mgmt.web.form.WfProcessInstanceForm(histProcInst.procInstId,execution.activityName,execution.state,histProcInst.processDuedate,wfBusInstance.masterEntity,wfBusInstance.masterEntityKey,wfBusInstance.busMemo1,wfBusInstance.busMemo2,wfBusInstance.busMemo3,wfBusInstance.busMemo4,wfBusInstance.busMemo5) " +
					" from Jbpm4Execution execution,Jbpm4HistProcinst histProcInst,WfBusInstance wfBusInstance " +
					" where execution.parent is null and execution.processInstanceId=histProcInst.procInstDbId and wfBusInstance.procInstId=histProcInst.procInstId ");
			
			//查找总记录数语句
			StringBuffer countHql = new StringBuffer("select count(execution.dbid) " +
					" from Jbpm4Execution execution,Jbpm4HistProcinst histProcInst,WfBusInstance wfBusInstance " +
					" where execution.parent is null and execution.processInstanceId=histProcInst.procInstDbId and wfBusInstance.procInstId=histProcInst.procInstId ");
			
			//要过滤的参数
			Map<String,Object> params = new HashMap<String, Object>();
			
			//拼装条件和设置条件相应的值
			if(StringUtils.isNotBlank(form.getId())){
				hql.append("and execution.id=:id ");
				countHql.append("and execution.id=:id ");
				params.put("id", form.getId());
			}
			
			if(StringUtils.isNotBlank(form.getState())){
				hql.append("and execution.state=:state ");
				countHql.append("and execution.state=:state ");
				params.put("state", form.getState());
			}
			
			if(StringUtils.isNotBlank(form.getActivityName())){
				hql.append("and execution.activityName=:activityName ");
				countHql.append("and execution.activityName=:activityName ");
				params.put("activityName", form.getActivityName());
			}
			
			if(form.getIsTimeOut() != null){
				if("是".equals(form.getIsTimeOut())){
					hql.append("and histProcInst.processDuedate < :processDuedate ");
					countHql.append("and histProcInst.processDuedate < :processDuedate ");
					params.put("processDuedate", new Date());
				}else{
					hql.append("and (histProcInst.processDuedate > :processDuedate or histProcInst.processDuedate is null) ");
					countHql.append("and (histProcInst.processDuedate > :processDuedate or histProcInst.processDuedate is null) ");
					params.put("processDuedate", new Date());
				}
			}
			
			
			if(StringUtils.isNotBlank(form.getProcessDefinitionKey())){
				if(form.getProcessDefinitioVersion() != null){
					String procdefId = WfUtils.convertToProcessDefinitionId(form.getProcessDefinitionKey(), form.getProcessDefinitioVersion());
					hql.append("and execution.procdefId=:procdefId ");
					countHql.append("and execution.procdefId=:procdefId ");
					params.put("procdefId", procdefId);
				}
				else{
					hql.append("and execution.procdefId like'"+form.getProcessDefinitionKey()+"%' ");
					countHql.append("and execution.procdefId like'"+form.getProcessDefinitionKey()+"%' ");
				}
			}

			hql.append("order by histProcInst.procInstDbId desc");
			
			//设置总记录数
			if (page.isAutoCount()) {
				long totalCount = countResult(countHql.toString(), params,page);
				page.setTotalCount(totalCount);
			}
			
			//查找流程实例集合
			Session session = this.getSession();
			Query query = session.createQuery(hql.toString());
			setParams(query,params,page);
			List<WfProcessInstanceForm> wfProcessInstanceForms = query.list();
			return wfProcessInstanceForms;
		}
		
		return null;
	}
	
	/**
	 * 获取集合的总记录数
	 * @param hql 查找的集合语句
	 * @param params 过滤的条件参数
	 * @param page 分页参数
	 * @return 返回集合记录数
	 */
	@SuppressWarnings("unchecked")
	private long countResult(String hql, Map<String,Object> params,Page page){
		Session session = this.getSession();
		Query query = session.createQuery(hql);
		
		//设置查找条件的参数
		setParams(query,params,null);
		
		Object result = query.uniqueResult();
		if(result != null){
			Long count = new Long(result.toString());
			return count.longValue();
		}
		
		return 0;
	}
	
	/**
	 * 设置查找条件的参数
	 * @param query Hibernate检索对象
	 * @param params 条件参数
	 * @param page 分页参数
	 */
	@SuppressWarnings("unchecked")
	private void setParams(Query query,Map<String,Object> params,Page page){
		Iterator iterator = params.entrySet().iterator();
		while(iterator.hasNext()){
			Map.Entry<String,Object> entry = (Map.Entry<String,Object>)iterator.next();
			query.setParameter(entry.getKey(), entry.getValue());
		}
		
		//设置分页数
		if(page != null){
			query.setFirstResult(page.getFirst()-1);
			query.setMaxResults(page.getPageSize());
		}
	}
}
